package com.wechat.pay;

import com.nsi.util.Httpsrequest;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.util.*;

/**
 * 微信支付工具类
 *
 * @author Luo Zhen
 */
@Slf4j
public class WxPaymentUtil {

    /**
     * 微信公众号支付
     *
     * @param openid
     * @return
     */
    public static SortedMap pay(String openid, String body, String total_fee, String attach) {
        String nonce_str = PayUtil.getRandomString(20);
        String out_trade_no = PayUtil.getCurrTime();

        //转换价格
        //价格单位转换：元 转为 分
        int total_fe = getTotalPrice(total_fee);

        //发起请求
        SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
        parameters.put("appid", WxPayConfig.appid);
        parameters.put("mch_id", WxPayConfig.mch_id);
        parameters.put("body", body);
        parameters.put("trade_type", WxPayConfig.trade_type2);
        parameters.put("nonce_str", nonce_str);
        parameters.put("notify_url", WxPayConfig.notify_url);
        parameters.put("out_trade_no", out_trade_no);
        parameters.put("total_fee", "" + total_fe + "");
        parameters.put("spbill_create_ip", WxPayConfig.spbill_create_ip);
        parameters.put("attach", attach);
        parameters.put("openid", openid);

        String sign = PayUtil.createSign("UTF-8", parameters, WxPayConfig.key);

        Pay pay = new Pay();
        pay.setAppid(WxPayConfig.appid);
        pay.setBody(body);
        pay.setMch_id(WxPayConfig.mch_id);
        pay.setNonce_str(nonce_str);
        pay.setNotify_url(WxPayConfig.notify_url);
        pay.setOpenid(openid);
        pay.setOut_trade_no(out_trade_no);
        pay.setSign(sign);
        pay.setSpbill_create_ip(WxPayConfig.spbill_create_ip);
        pay.setTrade_type(WxPayConfig.trade_type2);
        pay.setAttach(attach);
        pay.setTotal_fee(total_fe);

        Xstreamutil.xstream.alias("xml", Pay.class);
        String xml = Xstreamutil.xstream.toXML(pay).replaceAll("__", "_");

        //向这个地址发送请求POST
        String requestUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        String respxml = null;
        try {
            respxml = Httpsrequest.httpsRequest(requestUrl, "POST", xml);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //解析Xml
        String prepay_id = getString(respxml, "prepay_id");
        log.info("【微信公众号支付】prepay_id:{}", prepay_id);

        //二次验签
        String timeStamp = PayUtil.getTempStamp();
        String Package = "prepay_id=" + prepay_id;
        SortedMap<Object, Object> h5parameters = new TreeMap<Object, Object>();
        h5parameters.put("appId", WxPayConfig.appid);
        h5parameters.put("timeStamp", timeStamp);
        h5parameters.put("nonceStr", nonce_str);
        h5parameters.put("package", Package);
        h5parameters.put("signType", WxPayConfig.sign_type);

        //生成二次验签
        String Paysign = PayUtil.createSign("UTF-8", h5parameters, WxPayConfig.key);
        h5parameters.put("paySign", Paysign);

        return h5parameters;
    }

    /**
     * 微信H5 支付
     *
     * @param body
     * @param total_fee
     * @param attach
     * @param spbillIp
     * @param sceneInfo
     * @return
     */
    public static String payH5(String body, String total_fee, String attach, String spbillIp, String sceneInfo) {
        String nonce_str = PayUtil.getRandomString(20);
        String out_trade_no = PayUtil.getCurrTime() + PayUtil.getRandomString(5);

        int total_fe = getTotalPrice(total_fee);

        //场景信息
        String scene_info = "{\"h5_info\": {\"type\":\"wap\",\"wap_url\": \"data.xinxueshuo.cn\",\"wap_name\": \"" + sceneInfo + "\"}}";
        //发起请求
        SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
        parameters.put("appid", WxPayConfig.appid);
        parameters.put("mch_id", WxPayConfig.mch_id);
        parameters.put("body", body);
        parameters.put("trade_type", WxPayConfig.trade_type_h5);
        parameters.put("nonce_str", nonce_str);
        parameters.put("notify_url", WxPayConfig.notify_url);
        parameters.put("out_trade_no", out_trade_no);
        parameters.put("total_fee", "" + total_fe + "");
        parameters.put("spbill_create_ip", spbillIp);
        parameters.put("attach", attach);
        parameters.put("scene_info", scene_info);

        String sign = PayUtil.createSign("UTF-8", parameters, WxPayConfig.key);
        parameters.put("sign", sign);

        String requestXml = PayUtil.getRequestXml(parameters);
        log.info("【微信H5支付】requestXml:{}", requestXml);
        //向这个地址发送请求POST
        String requestUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        String respXml = null;
        try {
            respXml = Httpsrequest.httpsRequest(requestUrl, "POST", requestXml);
        } catch (Exception e) {
            log.error("【微信H5支付】发送参数失败:{}", e.getMessage());
        }

        // 解析Xml
        String mweb_url = getString(respXml, "mweb_url");
        log.info("mweb_url:{}", mweb_url);
        return mweb_url;
    }

    /**
     * 微信原生扫码支付
     *
     * @param body
     * @param total_fee
     * @param attach
     * @return
     */
    public static String payQrCode(String body, String total_fee, String attach, String out_trade_no) {
        String nonce_str = PayUtil.getRandomString(20);
//        String out_trade_no = PayUtil.getCurrTime() + PayUtil.getRandomString(5);

        int total_fe = getTotalPrice(total_fee);

        //发起请求
        SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
        parameters.put("appid", WxPayConfig.appid);
        parameters.put("mch_id", WxPayConfig.mch_id);
        parameters.put("nonce_str", nonce_str);
        parameters.put("body", body);
        parameters.put("out_trade_no", out_trade_no);
        parameters.put("total_fee", "" + total_fe + "");
        parameters.put("spbill_create_ip", WxPayConfig.spbill_create_ip);
        parameters.put("notify_url", WxPayConfig.notify_url);
        parameters.put("trade_type", WxPayConfig.trade_type_qr);
        parameters.put("attach", attach);
        parameters.put("device_info", WxPayConfig.device_info);
        parameters.put("product_id", "10001");

        String sign = PayUtil.createSign("UTF-8", parameters, WxPayConfig.key);
        parameters.put("sign", sign);

        String requestXml = PayUtil.getRequestXml(parameters);
        log.info("【微信扫码支付】requestXml:{}", requestXml);
        //向这个地址发送请求POST

        String requestUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        String respXml = null;
        try {
            respXml = Httpsrequest.httpsRequest(requestUrl, "POST", requestXml);
        } catch (Exception e) {
            log.error("【微信扫码支付】发送参数失败:{}", e.getMessage());
        }
        String codeUrl = getString(respXml, "code_url");
        String back = "https://api.qrserver.com/v1/create-qr-code/?size=160x160&data=" + codeUrl;
        return back;
    }

    /**
     * 解析 Xml
     *
     * @param respXml  微信返回参数
     * @param code_url 遍历取出的参数
     * @return
     */
    private static String getString(String respXml, String code_url) {
        String codeUrl = null;
        try {
            org.dom4j.Document document = DocumentHelper.parseText(respXml);
            //获取标签的根节点
            Element root = document.getRootElement();
            //获取根节点的子节点
            List<Element> elementList = root.elements();
            //便利
            for (int i = 0; i < elementList.size(); i++) {
                if (elementList.get(i).getName().equals(code_url)) {
                    codeUrl = elementList.get(i).getTextTrim();
                }
            }
        } catch (DocumentException e) {
            log.error("【解析XML】解析异常msg:{}", e.getMessage());
        }
        return codeUrl;
    }


//    -----------------支付模块改版- 以下为 新方法 ------------------

    /**
     * 微信 分转元
     *
     * @param total_fee
     * @return
     */
    private static int getTotalPrice(String total_fee) {
        double total_price = Double.parseDouble(total_fee);
        total_price = total_price * 100;
        return (int) total_price;
    }


    /**
     * 微信公众号支付
     *
     * @param openid
     * @return
     */
    public static SortedMap WxPay_public(String openid, String body, String total_fee, String out_trade_no, String attach) {
        String nonce_str = PayUtil.getRandomString(20);
        //价格单位转换：元 转为 分
        int total_fe = getTotalPrice(total_fee);

        //发起请求
        SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
        parameters.put("appid", WxPayConfig.appid);
        parameters.put("mch_id", WxPayConfig.mch_id);
        parameters.put("body", body);
        parameters.put("trade_type", WxPayConfig.trade_type2);
        parameters.put("nonce_str", nonce_str);
        parameters.put("notify_url", WxPayConfig.notify_url);
        parameters.put("out_trade_no", out_trade_no);
        parameters.put("total_fee", "" + total_fe + "");
        parameters.put("spbill_create_ip", WxPayConfig.spbill_create_ip);
        parameters.put("attach", attach);
        parameters.put("openid", openid);

        String sign = PayUtil.createSign("UTF-8", parameters, WxPayConfig.key);

        Pay pay = new Pay();
        pay.setAppid(WxPayConfig.appid);
        pay.setBody(body);
        pay.setMch_id(WxPayConfig.mch_id);
        pay.setNonce_str(nonce_str);
        pay.setNotify_url(WxPayConfig.notify_url);
        //pay.setOpenid(openid);
        pay.setOpenid(openid.replaceAll("__", "AAAAA"));
        pay.setOut_trade_no(out_trade_no);
        pay.setSign(sign);
        pay.setSpbill_create_ip(WxPayConfig.spbill_create_ip);
        pay.setTrade_type(WxPayConfig.trade_type2);
        pay.setAttach(attach);
        pay.setTotal_fee(total_fe);


        Xstreamutil.xstream.alias("xml", Pay.class);
        String xml = Xstreamutil.xstream.toXML(pay).replaceAll("__", "_");
        xml = xml.replaceAll("AAAAA", "__");
        log.info("【微信公众号支付】xml={}", xml);

        //向这个地址发送请求POST
        String requestUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        String respxml = null;
        try {
            respxml = Httpsrequest.httpsRequest(requestUrl, "POST", xml);
        } catch (Exception e) {
            log.error("【微信公众号支付】返回响应失败:{}", e.toString());
        }
        log.info("【微信公众号支付】respxml={}", respxml);

        //解析Xml
        String prepay_id = getString(respxml, "prepay_id");
        log.info("【微信公众号支付】prepay_id:{}", prepay_id);

        //二次验签
        String timeStamp = PayUtil.getTempStamp();
        String Package = "prepay_id=" + prepay_id;
        SortedMap<Object, Object> h5parameters = new TreeMap<Object, Object>();
        h5parameters.put("appId", WxPayConfig.appid);
        h5parameters.put("timeStamp", timeStamp);
        h5parameters.put("nonceStr", nonce_str);
        h5parameters.put("package", Package);
        h5parameters.put("signType", WxPayConfig.sign_type);

        //生成二次验签
        String Paysign = PayUtil.createSign("UTF-8", h5parameters, WxPayConfig.key);
        h5parameters.put("paySign", Paysign);

        return h5parameters;
    }

    /**
     * 微信小程序支付
     *
     * @param openid
     * @return
     */
    public static SortedMap WxPay_miniProgram(String openid, String body, String total_fee, String out_trade_no, String attach) {
        String nonce_str = PayUtil.getRandomString(20);
//        String out_trade_no = PayUtil.getCurrTime() + PayUtil.getRandomString(5);
        //价格单位转换：元 转为 分
        int total_fe = getTotalPrice(total_fee);

        //发起请求
        SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
        parameters.put("appid", WxPayConfig.appid_miniProgramShop);
        parameters.put("mch_id", WxPayConfig.mch_id);
        parameters.put("body", body);
        parameters.put("trade_type", WxPayConfig.trade_type2);
        parameters.put("nonce_str", nonce_str);
        parameters.put("notify_url", WxPayConfig.notify_url);
        parameters.put("out_trade_no", out_trade_no);
        parameters.put("total_fee", "" + total_fe + "");
        parameters.put("spbill_create_ip", WxPayConfig.spbill_create_ip);
        parameters.put("attach", attach);
        parameters.put("openid", openid);

        String sign = PayUtil.createSign("UTF-8", parameters, WxPayConfig.key);

        Pay pay = new Pay();
        pay.setAppid(WxPayConfig.appid_miniProgramShop);
        pay.setBody(body);
        pay.setMch_id(WxPayConfig.mch_id);
        pay.setNonce_str(nonce_str);
        pay.setNotify_url(WxPayConfig.notify_url);
//        pay.setOpenid(openid);
        pay.setOpenid(openid.replaceAll("__", "AAAAA"));
        pay.setOut_trade_no(out_trade_no);
        pay.setSign(sign);
        pay.setSpbill_create_ip(WxPayConfig.spbill_create_ip);
        pay.setTrade_type(WxPayConfig.trade_type2);
        pay.setAttach(attach);
        pay.setTotal_fee(total_fe);


        Xstreamutil.xstream.alias("xml", Pay.class);

        String xml = Xstreamutil.xstream.toXML(pay).replaceAll("__", "_");
        xml = xml.replaceAll("AAAAA", "__");

//        System.out.println("小程序支付发送xml:"+xml);
//        logger.info("xml:{}", xml);
        //向这个地址发送请求POST
        String requestUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        String respxml = null;
        try {
            respxml = Httpsrequest.httpsRequest(requestUrl, "POST", xml);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //解析Xml
        String prepay_id = getString(respxml, "prepay_id");
        log.info("【微信小程序支付】prepay_id:{}", prepay_id);


        //二次验签
        String timeStamp = PayUtil.getTempStamp();
        String Package = "prepay_id=" + prepay_id;
        SortedMap<Object, Object> h5parameters = new TreeMap<Object, Object>();
        h5parameters.put("appId", WxPayConfig.appid_miniProgramShop);
        h5parameters.put("timeStamp", timeStamp);
        h5parameters.put("nonceStr", nonce_str);
        h5parameters.put("package", Package);
        h5parameters.put("signType", WxPayConfig.sign_type);

        //生成二次验签
        String Paysign = PayUtil.createSign("UTF-8", h5parameters, WxPayConfig.key);
        h5parameters.put("paySign", Paysign);

        return h5parameters;
    }

}

